﻿using UnityEngine;
using UnityEditor;

namespace DragonRescue3D
{
    /// <summary>
    /// EditorWindow class defining our Level Editor.  This defines an interface that interacts
    /// with the scene view in order to place blocks and dragons around the map
    /// </summary>
    public class DRLevelEditor : EditorWindow
    {
        bool groupEnabled;
        bool myBool = true;
        float myFloat = 1.23f;
        Object[] _placeHolders;
        public int GridInt;
        public int CheckInt;

        //--------------------------------------------------------
        /// <summary>
        /// Initialise the window, and any other level editor specific info.
        /// </summary>
        [MenuItem("Window/Dragon Rescue 3D Level Editor")]
        static void Init()
        {
            // Load level template and position the view
            LoadTemplatePrefab();
            PositionCurrView();
            // Get existing open window or if none, make a new one:
            DRLevelEditor window = (DRLevelEditor)EditorWindow.GetWindow(typeof(DRLevelEditor));
            BlockPrefabs prefabs = GameObject.FindObjectOfType(typeof(BlockPrefabs)) as BlockPrefabs;
            // Attach a callback to the sceneview so we can intereact with the scene
            SceneView.onSceneGUIDelegate += window.SceneGUI;
            // We are in edit mode whenever we initialise the window
            prefabs._editMode = true;
            window._placeHolders = FindObjectsOfType(typeof(PlaceHolder));
        }

        //--------------------------------------------------------
        /// <summary>
        /// Loads in the level template prefab if one does not already exist in the scene
        /// </summary>
        static void LoadTemplatePrefab()
        {
            if (GameObject.FindGameObjectWithTag("LevelTemplate") == null)
            {
                Object LevelTemplatePrefab = AssetDatabase.LoadAssetAtPath(@"Assets/DragonRescue3D/Prefabs/LevelTemplate.prefab", typeof(GameObject));
                PrefabUtility.InstantiatePrefab(LevelTemplatePrefab);
            }
        }

        //--------------------------------------------------------
        /// <summary>
        /// Position the sceneview camera in front of the level template for editing
        /// </summary>
        /// <param name="camera">The editor camera</param>
        static void PositionCurrView()
        {
            // First, Find the location to set the camera to
            GameObject refPoint = GameObject.FindGameObjectWithTag("ReferencePoint");
            // Now, set the active view to position and rotation to look at the game template
            SceneView.lastActiveSceneView.pivot = refPoint.transform.position;
            SceneView.lastActiveSceneView.rotation = refPoint.transform.rotation;
        }

        //--------------------------------------------------------
        /// <summary>
        /// Displays the level editor interface.  This is a simple GUI enabling the user
        /// to select which game prefab (block/dragon) they would like to place in the scene
        /// </summary>
        void OnGUI()
        {
                Tools.current = Tool.None;
                Tools.viewTool = ViewTool.None;
                BlockPrefabs prefabs = GameObject.FindObjectOfType(typeof(BlockPrefabs)) as BlockPrefabs;
                Texture2D[] textures = new Texture2D[prefabs._blocks.Length + 1];
                int count = 0;
                prefabs._editMode = true;

                // Add preview textures of all our game prefabs to a list for use with our grid
                foreach (GameObject block in prefabs._blocks)
                {
                    textures[count++] = AssetPreview.GetAssetPreview(block);
                }

                // Add in the erase block texture at the end
                textures[count] = prefabs._eraseBlock;

                // First the title
                GUILayout.Label("Available Blocks", EditorStyles.boldLabel);

                // Now create our grid with our textures
                GUILayout.BeginHorizontal();
                GridInt = GUILayout.SelectionGrid(GridInt, textures, 4, GUILayout.Height(150), GUILayout.Width(300));
                GUILayout.EndHorizontal();

                if (GridInt != CheckInt)
                {
                    CheckInt = GridInt;
                }

                if (GridInt == count)
                {
                    prefabs._currentEditorBlock = null;
                }
                else
                {
                    prefabs._currentEditorBlock = prefabs._blocks[GridInt];
                }

                // Add in a button to reset our grid
                GUILayout.BeginHorizontal();
                if (GUILayout.Button(new GUIContent("Reset Grid", "Resets/Removes ALL objects from the level grid")))
                {
                    if (EditorUtility.DisplayDialog("Reset Grid?", "Are you sure you want to Reset the grid",
                                                    "Reset", "Cancel"))
                    {
                        ResetGrid();
                    }
                }
                GUILayout.EndHorizontal();

                // Add in a button to reset our grid
                GUILayout.BeginHorizontal();
                if (GUILayout.Button(new GUIContent("Reset View", "Resets the current camera view to line up with the level grid")))
                {
                    PositionCurrView();
                }
                GUILayout.EndHorizontal();

                // Add in a button to reset our grid
                GUILayout.BeginHorizontal();
                if (GUILayout.Button(new GUIContent("Reload Prefabs", "Reloads all prefab grid objects from disk.  This will need to be performed if the existing prefabs are changed in any way, or new prefabs are swapped in")))
                {
                    ReloadPrefabs();
                }
                GUILayout.EndHorizontal();
                SceneView.RepaintAll();
        }

        //--------------------------------------------------------
        /// <summary>
        /// Removes all our game prefabs (blocks/dragons) from the scene so we have an empty
        /// template
        /// </summary>
        void ResetGrid()
        {
            Selection.objects = new Object[0];
            Object[] gridObjs = GameObject.FindObjectsOfType(typeof(GridObject));
            
            // Clear out any existing child blocks 
            foreach (GridObject gridObj in gridObjs)
            {
                Undo.DestroyObjectImmediate(gridObj.gameObject);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        void ReloadPrefabs()
        {
            BlockPrefabs prefabs = GameObject.FindObjectOfType(typeof(BlockPrefabs)) as BlockPrefabs;
            Object[] gridObjects = GameObject.FindObjectsOfType(typeof(GridObject));

            foreach (GridObject gridObj in gridObjects)
            {
                foreach (GameObject prefab in prefabs._blocks)
                {
                    if (gridObj.gameObject.tag == prefab.tag)
                    {
                        Transform parentTransform = gridObj.gameObject.transform.parent;
                        Undo.DestroyObjectImmediate(gridObj.gameObject);
                        Object newInstance = Instantiate(prefab, parentTransform.position, parentTransform.rotation);
                        (newInstance as GameObject).transform.parent = parentTransform;
                        break;
                    }
                }
            }
        }

        //--------------------------------------------------------
        /// <summary>
        /// Delegate method that gets called whenever the scene view GUI gets refreshed. This
        /// is used to detect if a the user has clicked on a placeholder and if so, assigns the currently selected prefab
        /// to the position on the grid.
        /// </summary>
        /// <param name="sceneView"></param>
        void SceneGUI(SceneView sceneView)
        {
            Selection.objects = new Object[0];
            Tools.current = Tool.None;
            // This will have scene events including mouse down on scenes objects
            Event cur = Event.current;

            // Did the user click down on a mouse button?
            if (cur.type == EventType.MouseDown)
            {
                Selection.objects = new Object[0];
                RaycastHit hit;
                Ray mouseRay = sceneView.camera.ScreenPointToRay(new Vector3(cur.mousePosition.x, -cur.mousePosition.y + sceneView.camera.pixelHeight, 0));

                // Did the mouse get clicked on an object with a collider?
                if (Physics.Raycast(mouseRay, out hit))
                {
                    Transform trnsfrm = hit.transform;
                    Object obj = trnsfrm.GetComponent<PlaceHolder>();

                    // Have we hit a block instead of a placeholder?
                    if (obj == null)
                    {
                        obj = trnsfrm.parent.GetComponent<PlaceHolder>();
                    }

                    // If we have hit a place holder set the placeholder's prefab to the current prefab selected in the grid
                    if (obj != null)
                    {
                        BlockPrefabs prefabs = GameObject.FindObjectOfType(typeof(BlockPrefabs)) as BlockPrefabs;
                        PlaceHolder placeHolder = obj as PlaceHolder;
                        GridObject[] gridObjs = placeHolder.GetChildGridObjects();

                        // Destroy any existing grid objects attached to the placeholder
                        foreach (GridObject gridObj in gridObjs)
                        {
                            Undo.DestroyObjectImmediate(gridObj.gameObject);
                        }

                        // Create a new instance of the current block/object and attach it to the placeholder
                        if (prefabs._currentEditorBlock != null)
                        {
                            Object blockInstance = Instantiate(prefabs._currentEditorBlock, placeHolder.transform.position, placeHolder.transform.rotation);
                            Undo.RegisterCreatedObjectUndo(blockInstance, "Undo Block");
                            (blockInstance as GameObject).transform.parent = placeHolder.transform;
                        }
                    }
                }
            }
        }

        //--------------------------------------------------------
        /// <summary>
        /// Checks to see if the application is playing and closes the editor if it is
        /// </summary>
        void Update()
        {
            if (EditorApplication.isPlaying)
            {
                Close();
            }
        }

        //--------------------------------------------------------
        /// <summary>
        /// Make sure we remove any callbacks and set the edit mode to false when exiting the level editor
        /// </summary>
        void OnDestroy()
        {
            BlockPrefabs prefabs = GameObject.FindObjectOfType(typeof(BlockPrefabs)) as BlockPrefabs;
            prefabs._editMode = false;
            SceneView.onSceneGUIDelegate -= SceneGUI;
        }
    }
}

#if NO_AND_ERROR
public void TEXT1() 
{
	int textNum = 1;
	if (textNum == 1) 
	{
		textNum = 2;
    }
}
public void TEXT2()
{
    int textNum = 1;
    if (textNum == 1)
    {
        textNum = 2;
    }
}
public void TEXT3()
{
    int textNum = 1;
    if (textNum == 1)
    {
        textNum = 2;
    }
}

public void TEXT4()
{
    int textNum = 1;
    if (textNum == 1)
    {
        textNum = 2;
    }
}

public void TEXT5()
{
    int textNum = 1;
    if (textNum == 1)
    {
        textNum = 2;
    }
}

public void TEXT6()
{
    int textNum = 1;
    if (textNum == 1)
    {
        textNum = 2;
    }
}

public void TEXT8()
{
    int textNum = 1;
    if (textNum == 1)
    {
        textNum = 2;
    }
}

public void TEXT9()
{
    int textNum = 1;
    if (textNum == 1)
    {
        textNum = 2;
    }
}

public void TEXT10()
{
    int textNum = 1;
    if (textNum == 1)
    {
        textNum = 2;
    }
}

public void TEXT11()
{
    int textNum = 1;
    if (textNum == 1)
    {
        textNum = 2;
    }
}

public void TEXT12()
{
    int textNum = 1;
    if (textNum == 1)
    {
        textNum = 2;
    }
}

public void TEXT13()
{
    int textNum = 1;
    if (textNum == 1)
    {
        textNum = 2;
    }
}

public void TEXT14()
{
    int textNum = 1;
    if (textNum == 1)
    {
        textNum = 2;
    }
}

public void TEXT15()
{
    int textNum = 1;
    if (textNum == 1)
    {
        textNum = 2;
    }
}

public void TEXT16()
{
    int textNum = 1;
    if (textNum == 1)
    {
        textNum = 2;
    }
}

public void TEXT17()
{
    int textNum = 1;
    if (textNum == 1)
    {
        textNum = 2;
    }
}
#endif